# 执行顺序。就近原则，根据MRO这个顺序，先后找，找的顺序是递归的，从最里面开始找，也就是如下这个顺序，后面开始找，就近原则。
# MRO序列是: (<class '__main__.GrandSon'>, <class '__main__.Son2'>, <class '__main__.Son1'>, <class '__main__.Parent'>, <class 'object'>)
# parent的init函数执行了
# Son1的init函数执行了
# Son2的init函数执行了
# GrandSon的init函数执行了
# Son2的test函数执行了

class Parent(object):

    def __init__(self, name, *args, **kwargs):
        self.name = name
        print('parent的init函数执行了')

    def test(self):
        print('parent的test函数执行了')


class Son1(Parent):

    def __init__(self, name, age, *args, **kwargs):  # 严格意义上，这不是对父类Parent 的重写。
        self.age = age
        super().__init__(name, *args, **kwargs)
        print('Son1的init函数执行了')

    def test(self):  # 重写父类 的 test函数
        print('Son1的test函数执行了')


class Son2(Parent):

    def __init__(self, name, sex, *args, **kwargs):  # 参数中有name sex 没有age # 严格意义上，这不是对父类Parent 的重写。
        self.sex = sex  # 和 Son1 init 函数不太一样
        super().__init__(name, *args, **kwargs)  # 这个父类的__init__不会再调一次了，因为 初始化函数中 只会执行一次。
        print('Son2的init函数执行了')

    def test(self):  # 重写父类 的 test函数
        print('Son2的test函数执行了')


class GrandSon(Son2, Son1):  # 多继承

    def __init__(self, name, age, sex, *args, **kwargs):  # 参数中有name age sex，son1中有age参数所以优先执行。
        super().__init__(name, age, sex)
        print('GrandSon的init函数执行了')


print(f'MRO序列是: {GrandSon.__mro__}')  # MRO顺序
gs = GrandSon('zhangsan', 34, '男')
gs.test()

# 执行顺序。就近原则，根据MRO这个顺序，先后找，找的顺序是递归的，从最里面开始找，也就是如下这个顺序，后面开始找，就近原则。
# MRO序列是: (<class '__main__.GrandSon'>, <class '__main__.Son2'>, <class '__main__.Son1'>, <class '__main__.Parent'>, <class 'object'>)
# parent的init函数执行了
# Son1的init函数执行了
# Son2的init函数执行了
# GrandSon的init函数执行了
# Son2的test函数执行了

# 就近原则。

# 在python中是可以多继承的，继承的先后顺序是有区别的，当我们调用函数的时候，如果第一个继承的找不到，才会去第二个中找，
# 但是只要在第一个类中找到调用的那个函数，即使参数个数不匹配也不会调用第二个父类中的，此时会报错。

# MRO顺序：Python官方采用了一个算法将复杂结构上所有的类全部都映射到一个线性顺序上，而根据这个顺序就能够保证所有的类都会被构造一次。
